import sys
import time

from PyQt5.QtCore import QRect, QPointF
from PyQt5.QtGui import QBrush, QLinearGradient, QColor, QPen, QTextOption, QFontMetrics
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication
from qfluentwidgets import ListWidget


class ItemBase(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(ItemBase, self).__init__(parent)
        self.resize(500, 75)

        self.begin_width_spacing = 15  # 最开始时距离左右边框的位置
        self.begin_height_spacing = 16  # 最开始时距离上边框的位置
        self.icon_width = 40  # Icon宽度
        self.icon_height = 40  # Icon高度
        self.text_width_spacing = 12  # 字体内容距离气泡左右边框的距离
        self.text_height_spacing = 12  # 字体内容距离气泡上下边框的距离
        self.triangle_width = 6  # 三角形的宽度
        self.triangle_height = 10  # 三角形的高度
        self.triangle_height_spacing = 10
        self.text_min_width = 0
        self.min_width = 0
        self.text_max_width = 0
        self.real_width = 0
        self.text_height = 0


class RightItem(ItemBase):
    def __init__(self, parent=None, data=''):
        super(RightItem, self).__init__(parent)
        self.user_chat_content = data

    # 重写paintEvent 否则不能使用样式表定义外观
    def paintEvent(self, event):
        self.init_data()
        # 初始化QPainter对象，一支画笔
        painter = QtGui.QPainter(self)
        painter.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.SmoothPixmapTransform)
        font = QtGui.QFont()
        font.setFamily("实体")
        font.setPointSize(12)
        painter.setFont(font)
        # 画头像
        icon_rect = QRect(self.begin_width_spacing, self.begin_height_spacing, self.icon_width, self.icon_height)
        painter.setPen(QtCore.Qt.NoPen)
        painter.setBrush(QBrush(QtCore.Qt.gray))
        painter.drawPixmap(icon_rect, QtGui.QPixmap("AI.png"))
        # 画框架
        bubbleRect = QRect(self.begin_width_spacing + self.icon_width, self.begin_height_spacing,
                           self.triangle_width + self.text_width_spacing + self.text_max_width + self.text_width_spacing,
                           self.text_height_spacing + self.text_height + self.text_height_spacing)
        painter.setPen(QtCore.Qt.NoPen)
        painter.setBrush(QBrush(QColor(180, 180, 180)))
        painter.drawRoundedRect(bubbleRect.x() + self.triangle_width, bubbleRect.y(), bubbleRect.width() - self.triangle_width,
                                bubbleRect.height(), 18, 18)
        # QLinearGradient((x1,y1),(x2,y2))：点(x1,y1)到点(x2,y2)的渐变
        linearGradient = QLinearGradient(QPointF(bubbleRect.x() + self.triangle_width + 1, bubbleRect.y() + 1),
                                         QPointF(bubbleRect.x() + bubbleRect.width() - 1,
                                                 bubbleRect.y() + bubbleRect.height() - 1))
        linearGradient.setColorAt(0, QColor(151, 220, 227))
        linearGradient.setColorAt(0.25, QColor(151, 220, 227))
        linearGradient.setColorAt(0.5, QColor(151, 220, 227))
        linearGradient.setColorAt(0.75, QColor(151, 220, 227))
        linearGradient.setColorAt(1, QColor(151, 220, 227))

        painter.setBrush(linearGradient)

        painter.drawRoundedRect(bubbleRect.x() + self.triangle_width + 1, bubbleRect.y() + 1,
                                bubbleRect.width() - self.triangle_width - 2, bubbleRect.height() - 2, 18, 18)
        painter.setPen(QPen(QColor(244, 164, 96)))
        painter.drawPolygon(QPointF(bubbleRect.x(), bubbleRect.y() + self.triangle_height_spacing - 4),
                            QPointF(bubbleRect.x() + self.triangle_width + 1, bubbleRect.y() + self.triangle_height_spacing),
                            QPointF(bubbleRect.x() + 6 + 1, bubbleRect.y() + 10 + 10))

        painter.setPen(QPen(QColor(180, 180, 180)))
        painter.drawLine(QPointF(bubbleRect.x(), bubbleRect.y() + 10 - 4),
                         QPointF(bubbleRect.x() + 6, bubbleRect.y() + 10))
        painter.drawLine(QPointF(bubbleRect.x(), bubbleRect.y() + 10 - 4),
                         QPointF(bubbleRect.x() + 6, bubbleRect.y() + 10 + 10))
        # 画文字
        penText = QPen()
        penText.setColor(QColor(56, 56, 56))
        painter.setPen(penText)
        option = QTextOption(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
        # WrapAtWordBoundaryOrAnywhere：尽可能赶在单词的边界, 否则就在任意位置换行
        option.setWrapMode(QTextOption.WrapAtWordBoundaryOrAnywhere)
        painter.drawText(
            QtCore.QRectF(bubbleRect.x() + self.triangle_width + self.text_width_spacing, bubbleRect.y() + self.text_height_spacing,
                   self.text_max_width, self.text_height), self.user_chat_content, option)

    def init_data(self):
        """ 此函数用于初始化边框参数 """
        font = QtGui.QFont()
        font.setFamily("实体")
        font.setPointSize(12)
        # 提供关于字体的指标信息,QFontMetrics的函数用于计算给定字体的字符和字符串的大小
        metrics = QtGui.QFontMetrics(font)
        if metrics.width("A") * 2 + self.begin_height_spacing * 1.5 > self.text_width_spacing:
            self.text_min_width = self.begin_height_spacing * 1.5 - self.text_width_spacing
        else:
            self.text_min_width = 0
        self.min_width = self.begin_width_spacing + self.icon_width + self.triangle_width + self.text_width_spacing \
                         + self.text_width_spacing + self.icon_width + self.begin_width_spacing
        if self.width() < self.min_width + self.text_min_width:
            self.setMinimumWidth(self.min_width + self.text_min_width)
        self.text_max_width = self.width() - self.min_width

        self.real_width = metrics.width(self.user_chat_content)
        if self.real_width < self.text_max_width:
            self.text_max_width = self.real_width
            if self.text_height_spacing + metrics.height() + self.text_height_spacing > self.triangle_height_spacing +\
                    self.triangle_height + self.triangle_height_spacing:
                self.text_height = metrics.height()
            else:
                self.text_height = self.triangle_height_spacing + self.triangle_height + self.triangle_height_spacing
        else:
            flag = QtCore.Qt.TextWordWrap
            textRect = QtCore.QRect(0, 0, self.text_max_width, 0)
            # 自动换行
            textRect = metrics.boundingRect(textRect, flag, self.user_chat_content)
            self.text_height = textRect.height()


class LeftItem(ItemBase):
    def __init__(self, parent=None, data=""):
        super().__init__(parent=parent)
        self.user_chat_content = data

    # 重写paintEvent 否则不能使用样式表定义外观
    def paintEvent(self, event):
        self.init_data()

        # 初始化QPainter对象，一支画笔
        painter = QtGui.QPainter(self)
        painter.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.SmoothPixmapTransform)
        font = QtGui.QFont()
        font.setFamily("实体")
        font.setPointSize(12)
        painter.setFont(font)

        # 画框架
        bubbleRect = QRect(self.width()-(self.begin_width_spacing + self.icon_width + self.triangle_width +
                                         self.text_width_spacing + self.text_max_width + self.text_width_spacing),
                                        self.begin_height_spacing,
                           self.text_width_spacing + self.text_max_width + self.text_width_spacing + self.triangle_width,
                           self.text_height_spacing + self.text_height + self.text_height_spacing)
        painter.setPen(QtCore.Qt.NoPen)
        painter.setBrush(QBrush(QColor(180, 180, 180)))
        painter.drawRoundedRect(bubbleRect.x(), bubbleRect.y(),
                                bubbleRect.width() - self.triangle_width,
                                bubbleRect.height(), 18, 18)

        # QLinearGradient((x1,y1),(x2,y2))：点(x1,y1)到点(x2,y2)的渐变
        linearGradient = QLinearGradient(QPointF(bubbleRect.x() + 1, bubbleRect.y() + 1),
                                         QPointF(bubbleRect.x() + bubbleRect.width() - 1,
                                                 bubbleRect.y() + bubbleRect.height() - 1))
        # linearGradient.setColorAt(0, QColor(151, 220, 227))
        linearGradient.setColorAt(0, QColor(90, 231, 153))
        linearGradient.setColorAt(0.25, QColor(90, 231, 153))
        linearGradient.setColorAt(0.5, QColor(90, 231, 153))
        linearGradient.setColorAt(0.75, QColor(90, 231, 153))
        linearGradient.setColorAt(1, QColor(90, 231, 153))

        painter.setBrush(linearGradient)

        painter.drawRoundedRect(bubbleRect.x() + 1, bubbleRect.y() + 1,
                                bubbleRect.width() - self.triangle_width - 2, bubbleRect.height() - 2, 18, 18)
        # 画三角（多边形）
        painter.setPen(QPen(QColor(244, 164, 96)))
        painter.drawPolygon(QPointF(bubbleRect.x()+bubbleRect.width()-self.triangle_width-2,
                                    bubbleRect.y() + self.triangle_height_spacing),
                            QPointF(bubbleRect.x()+bubbleRect.width()-7, bubbleRect.y() + 20),
                            QPointF(bubbleRect.x()+bubbleRect.width(), bubbleRect.y()+self.triangle_height-4))

        painter.setPen(QPen(QColor(180, 180, 180)))
        painter.drawLine(QPointF(bubbleRect.x()+bubbleRect.width(), bubbleRect.y()+6),
                         QPointF(bubbleRect.x()+bubbleRect.width()-6, bubbleRect.y()+10))
        painter.drawLine(QPointF(bubbleRect.x()+bubbleRect.width(), bubbleRect.y()+6),
                         QPointF(bubbleRect.x()+bubbleRect.width()-6, bubbleRect.y()+20))
        # 画文字
        penText = QPen()
        penText.setColor(QColor(56, 56, 56))
        painter.setPen(penText)
        option = QTextOption(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
        # WrapAtWordBoundaryOrAnywhere：尽可能赶在单词的边界, 否则就在任意位置换行
        option.setWrapMode(QTextOption.WrapAtWordBoundaryOrAnywhere)
        painter.drawText(
            QtCore.QRectF(bubbleRect.x() + self.text_width_spacing,
                          bubbleRect.y() + self.text_height_spacing,
                          self.text_max_width, self.text_height), self.user_chat_content, option)

        # 画头像
        icon_rect = QRect(self.width()-self.icon_width-self.begin_width_spacing, self.begin_height_spacing, self.icon_width, self.icon_height)
        painter.setPen(QtCore.Qt.NoPen)
        painter.setBrush(QBrush(QtCore.Qt.gray))
        painter.drawPixmap(icon_rect, QtGui.QPixmap("boy.png"))

    def init_data(self):
        """ 此函数用于初始化边框参数 """
        font = QtGui.QFont()
        font.setFamily("实体")
        font.setPointSize(12)
        # 提供关于字体的指标信息,QFontMetrics的函数用于计算给定字体的字符和字符串的大小
        metrics = QtGui.QFontMetrics(font)
        if metrics.width("A") * 2 + self.begin_height_spacing * 1.5 > self.text_width_spacing:
            self.text_min_width = self.begin_height_spacing * 1.5 - self.text_width_spacing
        else:
            self.text_min_width = 0
        self.min_width = self.begin_width_spacing + self.icon_width + self.triangle_width + self.text_width_spacing \
                         + self.text_width_spacing + self.icon_width + self.begin_width_spacing
        if self.width() < self.min_width + self.text_min_width:
            self.setMinimumWidth(self.min_width + self.text_min_width)
        self.text_max_width = self.width() - self.min_width

        self.real_width = metrics.width(self.user_chat_content)
        if self.real_width < self.text_max_width:
            self.text_max_width = self.real_width
            if self.text_height_spacing + metrics.height() + self.text_height_spacing > self.triangle_height_spacing + \
                    self.triangle_height + self.triangle_height_spacing:
                self.text_height = metrics.height()
            else:
                self.text_height = self.triangle_height_spacing + self.triangle_height + self.triangle_height_spacing
        else:
            flag = QtCore.Qt.TextWordWrap
            textRect = QtCore.QRect(0, 0, self.text_max_width, 0)
            # 自动换行
            textRect = metrics.boundingRect(textRect, flag, self.user_chat_content)
            self.text_height = textRect.height()
        print(self.text_height)




class Win(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.resize(800, 400)
        self.item_count = 0
        self.item_space = 10

        self.central_widget = ListWidget(self)
        self.central_widget.setObjectName("central_widget")
        self.setCentralWidget(self.central_widget)
        self.central_widget.setStyleSheet("#central_widget::item{"
                                          "background-color:transparent;"
                                          "border:transparent};"
                                          "#central_widget::item:hover{"
                                          "background-color:transparent};"
                                          "#central_widget::item:selected{"
                                          "background-color:transparent};"
                                          "#central_widget{border:1px solid red;}")

        context = "this is a first dialog with AI,I don't know how to talk with it!"
        responce_1 = "点云设计结果如右图所示，根据你的要求，飞翼气动指标如下：" \
                     "Angle| CL | CD|\
                    xxx   |  xx | xx |\
                     xxx   |  xx | xx |\
                    ..\
                    我使用了气动设计模型完成了以上结果，并使用气动性能预测模型评估了设计结果和设计需求的符合程度"

        self.add_item("1234566677788", 0)
        self.add_item(responce_1, 1)
        self.add_item(context, 0)
        self.add_item(context, 1)

    def paintEvent(self, a0: QtGui.QPaintEvent) -> None:
        # 在改变界面大小时，根据每个item的字数动态改变每个item的大小
        for i in range(self.central_widget.count()):
            item = self.central_widget.item(i)
            item_widget = self.central_widget.itemWidget(item)
            height = item_widget.text_height + item_widget.text_height_spacing * 2 + \
                     item_widget.begin_height_spacing * 2
            item.setSizeHint(QtCore.QSize(300, height))

    def add_item(self, context, type_mess=0):

        if type_mess == 0:
            item_widget = LeftItem(data=context)
        else:
            item_widget = RightItem(data=context)
        item_widget.init_data()
        height = item_widget.text_height + item_widget.text_height_spacing * 2 + \
                 item_widget.begin_height_spacing * 2
        item = QtWidgets.QListWidgetItem()
        item.setSizeHint(QtCore.QSize(300, height))
        self.item_count += 1

        self.central_widget.addItem(item)
        self.central_widget.setItemWidget(item, item_widget)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Win()
    win.show()
    sys.exit(app.exec_())
